package za.co.smartmi.web.context;

import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest;

import za.co.smartmi.context.AccountContext;
import za.co.smartmi.context.LogContext;
import za.co.smartmi.security.Authenticator;
import za.co.smartmi.security.SpringSecurityContext;
import za.co.smartmi.service.SystemAccountService;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import za.co.smartmi.model.SystemAccount;
import za.co.smartmi.service.exception.ServiceException;

@Component
public class AccountContextSupport {
    private static final Logger log = Logger.getLogger(AccountContextSupport.class);

    private SystemAccountService accountService;

    @Autowired
    public AccountContextSupport(SystemAccountService accountService) {
        this.accountService = accountService;
    }

    /** 
     * Set up the LogContext and the AccountContext on the current thread.
     * Should be invoked once, e.g from your web filter or interceptor.
     * Do not forget to call the resetContext method when you are done
     * with the request.
     */
    public void processAccountContext(HttpServletRequest req) {
        String username = SpringSecurityContext.getUsername();

        // set up log context for this thread so these information can be used by log4j
        LogContext.setLogin(username != null ? username : "no username");
        LogContext.setSessionId(req.getSession().getId());

        // set up the account context
        AccountContext accountContext = new AccountContext();
        AccountContext.setAccountContext(accountContext);
        accountContext.setSessionId(req.getSession().getId());
        accountContext.setRoles(SpringSecurityContext.getRoles());

        if (SpringSecurityContext.getUserDetails() != null) {
            // load the account from the database.
            // we assume here that the second level cache is used,
            // otherwise we would hit the database at each request.
            SystemAccount account = new SystemAccount();
            try {
                account = accountService.getSystemAccount(username);
            } catch (ServiceException ex) {
                log.debug("ServiceException occurred: " + ex);
                account = null;
            }

            if (account != null) {
                // set up account context for this thread
                accountContext.setAccount(account);
                accountContext.setUsername(account.getSystemUser().getUsername());
            }
        } else if (log.isDebugEnabled()) {
            log.debug("No user details");
        }
    }

    /**
     * Reset the account context and the log context from the current thread.
     */
    public void resetContext() {
        AccountContext.resetAccountContext();
        LogContext.resetLogContext();
    }
}